/*
 * Copyright (c) 2010, Johan T. Larsson All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Mercenary Commander project nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *      
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL JOHAN T. LARSSON BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package games.TBSGame;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

public class ResourceManager {
	private Context AppContext;
	HashMap<Integer, Integer> TextureMap;
	static ResourceManager Singleton;
	
	FloatBuffer SquareCoords;
	FloatBuffer LargeSquareCoords;
	FloatBuffer SquareTexCoords;
	FloatBuffer HexCoords;
	FloatBuffer HexTexCoords;
	
	public ResourceManager(Context context)
	{
		AppContext = context;
		TextureMap = new HashMap<Integer, Integer>();
		Singleton = this;
		
		float vertices[] = {
				0.0f, 0.0f, 0,
				1.0f, 0.0f, 0,
				1.0f, 1.0f, 0,
				0.0f, 1.0f, 0};
		
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
	    vbb.order(ByteOrder.nativeOrder());
	    SquareCoords = vbb.asFloatBuffer();
	    SquareCoords.put(vertices);
	    SquareCoords.position(0);
	    
		float lVertices[] = {
				-0.25f, -0.25f, 0,
				1.25f, -0.25f, 0,
				1.25f, 1.25f, 0,
				-0.25f, 1.25f, 0};
		
		ByteBuffer lvbb = ByteBuffer.allocateDirect(lVertices.length * 4);
	    lvbb.order(ByteOrder.nativeOrder());
	    LargeSquareCoords = lvbb.asFloatBuffer();
	    LargeSquareCoords.put(lVertices);
	    LargeSquareCoords.position(0);

	    float texVertices[] = {
	    		0, 1,
	    		1, 1,
	    		1, 0,
	    		0, 0
	    };

	    ByteBuffer tbb = ByteBuffer.allocateDirect(texVertices.length * 4);
	    tbb.order(ByteOrder.nativeOrder());
	    SquareTexCoords = tbb.asFloatBuffer();
	    SquareTexCoords.put(texVertices);
	    SquareTexCoords.position(0);

	    float hexVertices[] = {
	    		0.5f, 1.15f, 0,
	    		1f, 0.85f, 0,
	    		1f, 0.15f, 0,
	    		0.5f, -0.15f, 0,
	    		0.0f, 0.15f, 0,
	    		0.0f, 0.85f, 0};

	    ByteBuffer hvbb = ByteBuffer.allocateDirect(hexVertices.length * 4);
	    hvbb.order(ByteOrder.nativeOrder());
	    HexCoords = hvbb.asFloatBuffer();
	    HexCoords.put(hexVertices);
	    HexCoords.position(0);
	    
	    //An approximation - but good enough for now
	    float hexTexVertices[] = {
	    		0.5f, 0,
	    		1, 0.22f,
	    		1, 0.78f,
	    		0.5f, 1,
	    		0, 0.78f,
	    		0, 0.22f		
	    };

	    ByteBuffer htbb = ByteBuffer.allocateDirect(hexTexVertices.length * 4);
	    htbb.order(ByteOrder.nativeOrder());
	    HexTexCoords = htbb.asFloatBuffer();
	    HexTexCoords.put(hexTexVertices);
	    HexTexCoords.position(0);
	}
	
	public void ReInit(GL10 gl)
	{
//		Collection tex = TextureMap.keySet();
//		Iterator iter = tex.iterator();
//		
//	    while(iter.hasNext())
//	    	LoadTexture(gl, iter.next());
//		}
	}
	
	public final Resources GetAppResources()
	{
		return AppContext.getResources();
	}
	
	public final AssetManager GetAppAssets()
	{
		return AppContext.getAssets();
	}
	
	public int LoadTexture(GL10 gl, int source)
	{
		int retVal = 0;
		if(TextureMap.containsKey(source))
			retVal = TextureMap.get(source);
		
		if(retVal != 0)
			return retVal;
		
		retVal = LoadTextureImpl(gl, source);
        
        TextureMap.put(source, retVal);        
        return retVal;
	}
	
	public void DeleteTexture(GL10 gl, int target)
	{
		if(!TextureMap.containsValue(target))
			return;

    	//God, I HATE JAVA!        	
    	IntBuffer tempId = IntBuffer.allocate(1);
    	tempId.put(target);
    	tempId.rewind();
    	gl.glDeleteTextures(1, tempId);
    	
    	TextureMap.values().remove(target);
	}
	
	private int LoadTextureImpl(GL10 gl, int source)
	{
        int[] textures = new int[1];
        gl.glGenTextures(1, textures, 0);
        int retVal = textures[0];
        gl.glBindTexture(GL10.GL_TEXTURE_2D, retVal);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
        InputStream is = AppContext.getResources().openRawResource(source);
        Bitmap bitmap;
        try {
            bitmap = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch(IOException e) {
                // Empty
            	//TODO: How to handle?
            	DeleteTexture(gl, retVal);
            	retVal = 0;
            }
        }
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
	        
        bitmap.recycle();
        
        return retVal;
	}
}
